/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.mzk.lidovky.articles.krameriusAccess;

import cz.mzk.rehan.commons.DatastreamId;
import cz.mzk.kramerius.fedoraaccess.FedoraConnector;
import cz.mzk.rehan.commons.Dom4jUtils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.dom4j.Document;
import org.dom4j.Node;
import org.dom4j.XPath;

/**
 *
 * @author Martin Řehánek (rehan@mzk.cz)
 */
public class IssueAccessImpl implements IssueAccess {

    private String issuePid;
    private Map<Integer, String> pageNumberPidMap;//pageNumber:page PID
    private FedoraConnector connector;
    private static String PAGE_PID_PREFIX = "info:fedora/";

    public IssueAccessImpl(String issuePid, FedoraConnector connector) {
        this.issuePid = issuePid;
        this.connector = connector;
        pageNumberPidMap = new HashMap<Integer, String>();
        initPagePidMap();
    }

    private void initPagePidMap() {
        List<String> pagePidList = getPages();
        for (String pagePid : pagePidList) {
            Integer pageNumber = getPageNumber(pagePid);
            if (pageNumber == null) {
                Logger.getLogger(PeriodicalAccessImpl.class.getName()).log(Level.SEVERE, "No page number in BIBLIO_MODS stream for page with pid ''{0}''", pagePid);
            } else {
                addPageNumberPidMapping(pageNumber, pagePid);
            }
        }
        //printPageNumberPidMapping();
    }

    private List<String> getPages() {
        Document relsExtDoc = connector.getDatastreamDissemination(issuePid, DatastreamId.RELS_EXT);
        XPath xpath = Dom4jUtils.createXPath("//kramerius:hasPage/@rdf:resource");
        List<Node> attributeNodes = xpath.selectNodes(relsExtDoc);
        //List<Node> attributeNodes = relsExtDoc.selectNodes("//kramerius:hasPage/@rdf:resource");
        List<String> pidList = new ArrayList<String>();
        for (Node node : attributeNodes) {
            String prefixedPid = node.getText();
            //System.out.println("prefixed: " + prefixedPid);
            String pid = prefixedPid.substring(PAGE_PID_PREFIX.length());
            //System.out.println("pid: " + pid);
            pidList.add(pid);
        }
        return pidList;
    }

    private Integer getPageNumber(String pagePid) {
        Document modsDoc = connector.getDatastreamDissemination(pagePid, DatastreamId.BIBLIO_MODS);
        XPath xpath = Dom4jUtils.createXPath("//mods:part[@type='TitlePage']/mods:detail[@type='pageNumber']/mods:number|"
                + "//mods:part[@type='NormalPage']/mods:detail[@type='pageNumber']/mods:number|"
                + "//mods:part[@type='Advertisement']/mods:detail[@type='pageNumber']/mods:number");
        Node pageNumNode = xpath.selectSingleNode(modsDoc);
        //Node pageNumNode = modsDoc.selectSingleNode("//mods:part[@type='TitlePage']/mods:detail[@type='pageNumber']/mods:number|"
        //        + "//mods:part[@type='NormalPage']/mods:detail[@type='pageNumber']/mods:number|"
        //        + "//mods:part[@type='Advertisement']/mods:detail[@type='pageNumber']/mods:number");
        String pageNumStr;
        if (pageNumNode == null || (pageNumStr = pageNumNode.getText()) == null) {
            Logger.getLogger(IssueAccessImpl.class.getName()).log(Level.SEVERE, "Cannot find content of element mods:number for page with pid ''{0}''", pagePid);
            return null;
        }
        Integer pageNum = null;
        try {
            pageNum = parsePageNumber(pageNumStr);
        } catch (NumberFormatException e) {
            Logger.getLogger(IssueAccessImpl.class.getName()).log(Level.SEVERE, "Illegal value in element mods:number ''{0}'' for page with pid ''{1}''", new Object[]{pageNumStr, pagePid});
            return null;
        }
        //taky se to da zjistit z dc:title. Tam byva "cislo_strany" nebo "[cislo_strany]" u prvni strany
        return pageNum;
    }

    private Integer parsePageNumber(String pageNumberStr) throws NumberFormatException {
        if (pageNumberStr.contains("[")) { //[1]
            return Integer.parseInt(pageNumberStr.substring(1, pageNumberStr.length() - 1));
        } else {
            return Integer.parseInt(pageNumberStr);
        }
    }

    /**
     *
     * @param pageNumber
     * @param pagePid
     */
    private void addPageNumberPidMapping(Integer pageNumber, String pagePid) {
        String oldPid = pageNumberPidMap.get(pageNumber);
        if (oldPid != null) {
            Logger.getLogger(IssueAccessImpl.class.getName()).log(Level.SEVERE, "pid for page {0} already present. Found pid: ''{1}'', wanted to add pid: ''{2}'' ", new Object[]{pageNumber, oldPid, pagePid});
        }
        pageNumberPidMap.put(pageNumber, pagePid);
    }

    @Override
    public String getIssuePid() {
        return issuePid;
    }

    @Override
    public String getPagePid(Integer pageNumber) {
        return pageNumberPidMap.get(pageNumber);
    }

    @Override
    public Collection<String> getPagePidCollection() {
        return pageNumberPidMap.values();
    }

    private void printPageNumberPidMapping() {
        System.out.println("printing map for issue with pid " + issuePid);
        for (Integer key : pageNumberPidMap.keySet()) {
            System.out.println(key + ":" + pageNumberPidMap.get(key));
        }
    }
}
